package com.itheima.behavior.stream;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itheima.behavior.config.KafkaConfig;
import com.itheima.common.redis.CacheService;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.kstream.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 排行榜流式处理器
 * 使用 Kafka Streams 实时处理用户行为，计算并更新排行榜到 Redis
 */
@Component
@Slf4j
public class RankingStreamProcessor {

    @Autowired
    private CacheService cacheService;

    // 行为权重配置
    private static final double WEIGHT_VIEW = 0.1;      // 浏览权重
    private static final double WEIGHT_READING = 1.0;   // 阅读权重
    private static final double WEIGHT_LIKE = 2.0;      // 点赞权重
    private static final double WEIGHT_COLLECT = 3.0;   // 收藏权重
    private static final double WEIGHT_NOTE = 2.5;      // 笔记权重
    private static final double WEIGHT_REVIEW = 3.5;    // 书评权重

    // 用于聚合统计的内存缓存（定期更新到 Redis）
    private final Map<String, BookStats> bookStatsCache = new ConcurrentHashMap<>();
    private final Map<Integer, UserStats> userStatsCache = new ConcurrentHashMap<>();

    /**
     * 构建 Kafka Streams 拓扑
     */
    @Bean
    public KStream<String, String> buildRankingStream(StreamsBuilder streamsBuilder) {
        log.info("========== 开始构建 Kafka Streams 拓扑 ==========");
        
        // 1. 从 user-behavior topic 读取用户行为事件流
        KStream<String, String> behaviorStream = streamsBuilder
                .stream(KafkaConfig.Topics.USER_BEHAVIOR,
                        Consumed.with(Serdes.String(), Serdes.String()));
        
        log.info("订阅 Topic: {}", KafkaConfig.Topics.USER_BEHAVIOR);
        
        // 添加日志监控：打印每条接收到的消息
        behaviorStream.peek((key, value) -> 
            log.info("收到行为事件: key={}, value={}", key, value)
        );

        // 2. 过滤出图书相关的行为
        KStream<String, String> bookBehaviorStream = behaviorStream
                .filter((key, value) -> {
                    try {
                        JSONObject json = JSON.parseObject(value);
                        String targetType = json.getString("targetType");
                        boolean isBook = "book".equals(targetType);
                        if (isBook) {
                            log.info("✅ 过滤到图书行为事件: behaviorType={}, bookId={}", 
                                json.getString("behaviorType"), 
                                json.getString("targetId"));
                        }
                        return isBook;
                    } catch (Exception e) {
                        log.error("解析行为事件失败: {}", value, e);
                        return false;
                    }
                });

        // 3. 实时处理每个图书行为事件（不使用窗口聚合，直接更新）
        bookBehaviorStream.foreach((key, value) -> {
            try {
                JSONObject json = JSON.parseObject(value);
                String bookId = json.getString("targetId");
                String behaviorType = json.getString("behaviorType");
                Integer userId = json.getInteger("userId");
                
                // 验证 bookId 必须是纯数字
                if (bookId == null || bookId.isEmpty() || !bookId.matches("^\\d+$")) {
                    log.warn("⚠️ 跳过无效的图书ID: bookId={}, behaviorType={}", bookId, behaviorType);
                    return;
                }
                
                log.info("📊 开始处理图书行为: bookId={}, behaviorType={}, userId={}", 
                    bookId, behaviorType, userId);
                
                // 直接更新排行榜
                processBookBehaviorRealtime(bookId, behaviorType, userId, json);
                
            } catch (Exception e) {
                log.error("处理图书行为失败: {}", value, e);
            }
        });

        // 7. 处理用户阅读时长排行榜
        buildUserReadingRanking(behaviorStream);

        // 8. 处理用户活跃度排行榜
        buildUserActiveRanking(behaviorStream);

        // 9. 处理笔记热度排行榜
        buildNoteHotRanking(behaviorStream);

        // 10. 处理书评热度排行榜
        buildReviewHotRanking(behaviorStream);

        log.info("Kafka Streams 排行榜处理器初始化完成");
        return behaviorStream;
    }

    /**
     * 初始化图书统计数据
     */
    private String initBookStats() {
        BookStats stats = new BookStats();
        return JSON.toJSONString(stats);
    }

    /**
     * 聚合用户行为数据
     */
    private String aggregateBehavior(String bookId, String behavior, String currentStats) {
        try {
            BookStats stats = JSON.parseObject(currentStats, BookStats.class);
            JSONObject behaviorJson = JSON.parseObject(behavior);

            String behaviorType = behaviorJson.getString("behaviorType");
            Integer userId = behaviorJson.getInteger("userId");

            // 根据行为类型更新统计
            switch (behaviorType) {
                case "book_view":
                case "page_view":
                    stats.viewCount++;
                    break;
                case "reading":
                case "reading_start":
                    stats.readingUserIds.add(userId);
                    stats.readingCount = stats.readingUserIds.size();
                    break;
                case "reading_end":
                    Integer duration = behaviorJson.getInteger("duration");
                    if (duration != null) {
                        stats.totalReadingTime += duration;
                    }
                    break;
                case "like":
                    stats.likeCount++;
                    break;
                case "collect":
                    stats.collectCount++;
                    break;
                case "note_create":
                    stats.noteCount++;
                    break;
                case "review_create":
                    stats.reviewCount++;
                    break;
            }

            // 计算热度分数
            stats.popularityScore = calculatePopularityScore(stats);
            stats.lastUpdateTime = System.currentTimeMillis();

            return JSON.toJSONString(stats);

        } catch (Exception e) {
            log.error("聚合行为数据失败: bookId={}, behavior={}", bookId, behavior, e);
            return currentStats;
        }
    }

    /**
     * 计算热度分数
     */
    private double calculatePopularityScore(BookStats stats) {
        return stats.viewCount * WEIGHT_VIEW
                + stats.readingCount * WEIGHT_READING
                + stats.likeCount * WEIGHT_LIKE
                + stats.collectCount * WEIGHT_COLLECT
                + stats.noteCount * WEIGHT_NOTE
                + stats.reviewCount * WEIGHT_REVIEW;
    }

    /**
     * 实时处理图书行为（直接更新，无需等待窗口）
     */
    private void processBookBehaviorRealtime(String bookId, String behaviorType, Integer userId, JSONObject behaviorJson) {
        try {
            log.info("🔥 实时处理图书行为: bookId={}, type={}, user={}", bookId, behaviorType, userId);
            
            // 根据不同行为类型计算权重分数
            double score = 0.0;
            
            switch (behaviorType) {
                case "book_view":
                    score = WEIGHT_VIEW;
                    // 增加实时浏览排行榜分数
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, bookId, score);
                    log.info("✅ 更新浏览热度: bookId={}, score=+{}", bookId, score);
                    break;
                    
                case "reading_start":
                case "reading_end":
                    score = WEIGHT_READING;
                    // 增加阅读排行榜分数
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_READ_RANKING, bookId, score);
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, bookId, score);
                    log.info("✅ 更新阅读热度: bookId={}, score=+{}", bookId, score);
                    break;
                    
                case "like":
                    score = WEIGHT_LIKE;
                    // 增加点赞排行榜分数
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_LIKE_RANKING, bookId, score);
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, bookId, score);
                    log.info("✅ 更新点赞热度: bookId={}, score=+{}", bookId, score);
                    break;
                    
                case "collect":
                    score = WEIGHT_COLLECT;
                    // 增加收藏排行榜分数
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_COLLECT_RANKING, bookId, score);
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, bookId, score);
                    log.info("✅ 更新收藏热度: bookId={}, score=+{}", bookId, score);
                    break;
                    
                case "note_create":
                    score = WEIGHT_NOTE;
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, bookId, score);
                    log.info("✅ 更新笔记热度: bookId={}, score=+{}", bookId, score);
                    break;
                    
                case "review_create":
                    score = WEIGHT_REVIEW;
                    cacheService.zIncrementScore(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, bookId, score);
                    log.info("✅ 更新书评热度: bookId={}, score=+{}", bookId, score);
                    break;
                    
                default:
                    log.debug("未处理的行为类型: {}", behaviorType);
                    break;
            }
            
            // 定期裁剪排行榜，只保留 Top 500
            if (Math.random() < 0.01) { // 1% 概率执行清理
                trimAndExpireRanking(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, 500, 7200);
                trimAndExpireRanking(KafkaConfig.Keys.BOOK_REALTIME_READ_RANKING, 500, 7200);
                trimAndExpireRanking(KafkaConfig.Keys.BOOK_REALTIME_COLLECT_RANKING, 500, 7200);
                trimAndExpireRanking(KafkaConfig.Keys.BOOK_REALTIME_LIKE_RANKING, 500, 7200);
                log.info("🧹 执行排行榜清理");
            }
            
        } catch (Exception e) {
            log.error("❌ 实时处理图书行为失败: bookId={}, type={}", bookId, behaviorType, e);
        }
    }

    /**
     * 更新图书排行榜到 Redis
     * Kafka Streams 更新的是实时排行榜，反映当前热度
     */
    private void updateBookRanking(String bookId, String statsJson) {
        try {
            BookStats stats = JSON.parseObject(statsJson, BookStats.class);

            // 缓存到内存
            bookStatsCache.put(bookId, stats);

            // ========== 更新实时排行榜到 Redis ZSet ==========
            // 实时排行榜反映近期（如最近1小时）的热度，用于发现新热点
            
            // 1. 实时综合热度排行榜（Kafka Streams 实时计算）
            cacheService.zAdd(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, bookId, stats.popularityScore);

            // 2. 实时阅读人数排行榜
            cacheService.zAdd(KafkaConfig.Keys.BOOK_REALTIME_READ_RANKING, bookId, stats.readingCount);

            // 3. 实时收藏数排行榜
            cacheService.zAdd(KafkaConfig.Keys.BOOK_REALTIME_COLLECT_RANKING, bookId, stats.collectCount);

            // 4. 实时点赞数排行榜
            cacheService.zAdd(KafkaConfig.Keys.BOOK_REALTIME_LIKE_RANKING, bookId, stats.likeCount);

            // 实时榜只保留 Top 500，并设置过期时间（2小时）
            trimAndExpireRanking(KafkaConfig.Keys.BOOK_REALTIME_HOT_RANKING, 500, 7200);
            trimAndExpireRanking(KafkaConfig.Keys.BOOK_REALTIME_READ_RANKING, 500, 7200);
            trimAndExpireRanking(KafkaConfig.Keys.BOOK_REALTIME_COLLECT_RANKING, 500, 7200);
            trimAndExpireRanking(KafkaConfig.Keys.BOOK_REALTIME_LIKE_RANKING, 500, 7200);

            log.debug("更新实时排行榜: bookId={}, score={}, reading={}, collect={}, like={}",
                    bookId, stats.popularityScore, stats.readingCount, stats.collectCount, stats.likeCount);

        } catch (Exception e) {
            log.error("更新实时排行榜到Redis失败: bookId={}", bookId, e);
        }
    }

    /**
     * 裁剪排行榜并设置过期时间
     */
    private void trimAndExpireRanking(String key, int maxSize, int expireSeconds) {
        try {
            // 只保留 Top N
            Long size = cacheService.zSize(key);
            if (size != null && size > maxSize) {
                cacheService.zRemoveRange(key, 0, -maxSize - 1);
            }
            
            // 设置过期时间
            cacheService.expire(key, expireSeconds, java.util.concurrent.TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("裁剪排行榜失败: key={}", key, e);
        }
    }

    /**
     * 构建用户阅读时长排行榜
     */
    private void buildUserReadingRanking(KStream<String, String> behaviorStream) {
        behaviorStream
                .filter((key, value) -> {
                    try {
                        JSONObject json = JSON.parseObject(value);
                        return "reading_end".equals(json.getString("behaviorType"));
                    } catch (Exception e) {
                        return false;
                    }
                })
                .groupBy(
                        (key, value) -> {
                            JSONObject json = JSON.parseObject(value);
                            return json.getInteger("userId").toString();
                        },
                        Grouped.with(Serdes.String(), Serdes.String())
                )
                .windowedBy(TimeWindows.of(Duration.ofMinutes(5)))
                .aggregate(
                        () -> "0",
                        (userId, behavior, totalTime) -> {
                            try {
                                JSONObject json = JSON.parseObject(behavior);
                                Integer duration = json.getInteger("duration");
                                if (duration == null) duration = 0;
                                int current = Integer.parseInt(totalTime);
                                return String.valueOf(current + duration);
                            } catch (Exception e) {
                                return totalTime;
                            }
                        },
                        Materialized.with(Serdes.String(), Serdes.String())
                )
                .toStream()
                .foreach((windowedKey, totalTime) -> {
                    try {
                        String userId = windowedKey.key();
                        int timeInMinutes = Integer.parseInt(totalTime) / 60;
                        
                        // 更新用户阅读时长排行榜
                        cacheService.zAdd(KafkaConfig.Keys.USER_READING_TIME_RANKING, userId, timeInMinutes);
                        
                        log.debug("更新用户阅读时长: userId={}, time={}分钟", userId, timeInMinutes);
                    } catch (Exception e) {
                        log.error("更新用户阅读时长排行榜失败", e);
                    }
                });
    }

    /**
     * 构建用户活跃度排行榜
     */
    private void buildUserActiveRanking(KStream<String, String> behaviorStream) {
        behaviorStream
                .groupBy(
                        (key, value) -> {
                            try {
                                JSONObject json = JSON.parseObject(value);
                                return json.getInteger("userId").toString();
                            } catch (Exception e) {
                                return "unknown";
                            }
                        },
                        Grouped.with(Serdes.String(), Serdes.String())
                )
                .windowedBy(TimeWindows.of(Duration.ofMinutes(5)))
                .count(Materialized.with(Serdes.String(), Serdes.Long()))
                .toStream()
                .foreach((windowedKey, count) -> {
                    try {
                        String userId = windowedKey.key();
                        if (!"unknown".equals(userId)) {
                            // 更新用户活跃度排行榜（以行为次数作为活跃度）
                            cacheService.zAdd(KafkaConfig.Keys.USER_ACTIVE_RANKING, userId, count.doubleValue());
                            
                            log.debug("更新用户活跃度: userId={}, count={}", userId, count);
                        }
                    } catch (Exception e) {
                        log.error("更新用户活跃度排行榜失败", e);
                    }
                });
    }

    /**
     * 构建笔记热度排行榜
     * 笔记热度公式: 浏览*0.1 + 点赞*2.0 + 收藏*3.0 + 评论*1.5
     */
    private void buildNoteHotRanking(KStream<String, String> behaviorStream) {
        behaviorStream
                .filter((key, value) -> {
                    try {
                        JSONObject json = JSON.parseObject(value);
                        return "note".equals(json.getString("targetType"));
                    } catch (Exception e) {
                        return false;
                    }
                })
                .groupBy(
                        (key, value) -> {
                            JSONObject json = JSON.parseObject(value);
                            return json.getString("targetId"); // 笔记ID
                        },
                        Grouped.with(Serdes.String(), Serdes.String())
                )
                .windowedBy(TimeWindows.of(Duration.ofMinutes(5)))
                .aggregate(
                        () -> initNoteStats(),
                        (noteId, behavior, aggValue) -> aggregateNoteStats(noteId, behavior, aggValue),
                        Materialized.with(Serdes.String(), Serdes.String())
                )
                .toStream()
                .foreach((windowedKey, statsJson) -> {
                    try {
                        String noteId = windowedKey.key();
                        updateNoteRanking(noteId, statsJson);
                    } catch (Exception e) {
                        log.error("更新笔记排行榜失败: key={}", windowedKey, e);
                    }
                });
    }

    /**
     * 构建书评热度排行榜
     * 书评热度公式: 浏览*0.1 + 点赞*2.0 + 收藏*3.0 + 评论*1.5 + 有用标记*2.5
     */
    private void buildReviewHotRanking(KStream<String, String> behaviorStream) {
        behaviorStream
                .filter((key, value) -> {
                    try {
                        JSONObject json = JSON.parseObject(value);
                        return "review".equals(json.getString("targetType"));
                    } catch (Exception e) {
                        return false;
                    }
                })
                .groupBy(
                        (key, value) -> {
                            JSONObject json = JSON.parseObject(value);
                            return json.getString("targetId"); // 书评ID
                        },
                        Grouped.with(Serdes.String(), Serdes.String())
                )
                .windowedBy(TimeWindows.of(Duration.ofMinutes(5)))
                .aggregate(
                        () -> initReviewStats(),
                        (reviewId, behavior, aggValue) -> aggregateReviewStats(reviewId, behavior, aggValue),
                        Materialized.with(Serdes.String(), Serdes.String())
                )
                .toStream()
                .foreach((windowedKey, statsJson) -> {
                    try {
                        String reviewId = windowedKey.key();
                        updateReviewRanking(reviewId, statsJson);
                    } catch (Exception e) {
                        log.error("更新书评排行榜失败: key={}", windowedKey, e);
                    }
                });
    }

    /**
     * 初始化笔记统计数据
     */
    private String initNoteStats() {
        NoteStats stats = new NoteStats();
        return JSON.toJSONString(stats);
    }

    /**
     * 初始化书评统计数据
     */
    private String initReviewStats() {
        ReviewStats stats = new ReviewStats();
        return JSON.toJSONString(stats);
    }

    /**
     * 聚合笔记统计数据
     */
    private String aggregateNoteStats(String noteId, String behavior, String currentStats) {
        try {
            NoteStats stats = JSON.parseObject(currentStats, NoteStats.class);
            JSONObject behaviorJson = JSON.parseObject(behavior);
            String behaviorType = behaviorJson.getString("behaviorType");

            switch (behaviorType) {
                case "note_view":
                    stats.viewCount++;
                    break;
                case "like":
                    stats.likeCount++;
                    break;
                case "collect":
                    stats.collectCount++;
                    break;
                case "comment":
                    stats.commentCount++;
                    break;
            }

            // 计算热度分数: 浏览*0.1 + 点赞*2.0 + 收藏*3.0 + 评论*1.5
            stats.hotScore = stats.viewCount * 0.1 
                    + stats.likeCount * 2.0 
                    + stats.collectCount * 3.0 
                    + stats.commentCount * 1.5;
            
            stats.lastUpdateTime = System.currentTimeMillis();
            return JSON.toJSONString(stats);

        } catch (Exception e) {
            log.error("聚合笔记统计失败: noteId={}", noteId, e);
            return currentStats;
        }
    }

    /**
     * 聚合书评统计数据
     */
    private String aggregateReviewStats(String reviewId, String behavior, String currentStats) {
        try {
            ReviewStats stats = JSON.parseObject(currentStats, ReviewStats.class);
            JSONObject behaviorJson = JSON.parseObject(behavior);
            String behaviorType = behaviorJson.getString("behaviorType");

            switch (behaviorType) {
                case "review_view":
                    stats.viewCount++;
                    break;
                case "like":
                    stats.likeCount++;
                    break;
                case "collect":
                    stats.collectCount++;
                    break;
                case "comment":
                    stats.commentCount++;
                    break;
                case "helpful": // 标记为有用
                    stats.helpfulCount++;
                    break;
            }

            // 计算热度分数: 浏览*0.1 + 点赞*2.0 + 收藏*3.0 + 评论*1.5 + 有用*2.5
            stats.hotScore = stats.viewCount * 0.1 
                    + stats.likeCount * 2.0 
                    + stats.collectCount * 3.0 
                    + stats.commentCount * 1.5 
                    + stats.helpfulCount * 2.5;
            
            stats.lastUpdateTime = System.currentTimeMillis();
            return JSON.toJSONString(stats);

        } catch (Exception e) {
            log.error("聚合书评统计失败: reviewId={}", reviewId, e);
            return currentStats;
        }
    }

    /**
     * 更新笔记排行榜到 Redis
     */
    private void updateNoteRanking(String noteId, String statsJson) {
        try {
            NoteStats stats = JSON.parseObject(statsJson, NoteStats.class);

            // 更新实时热门笔记排行榜
            cacheService.zAdd(KafkaConfig.Keys.NOTE_REALTIME_HOT_RANKING, noteId, stats.hotScore);
            
            // 更新笔记点赞排行榜
            cacheService.zAdd(KafkaConfig.Keys.NOTE_LIKE_RANKING, noteId, stats.likeCount);
            
            // 更新笔记收藏排行榜
            cacheService.zAdd(KafkaConfig.Keys.NOTE_COLLECT_RANKING, noteId, stats.collectCount);

            // 只保留 Top 500，设置2小时过期
            trimAndExpireRanking(KafkaConfig.Keys.NOTE_REALTIME_HOT_RANKING, 500, 7200);
            trimAndExpireRanking(KafkaConfig.Keys.NOTE_LIKE_RANKING, 500, 7200);
            trimAndExpireRanking(KafkaConfig.Keys.NOTE_COLLECT_RANKING, 500, 7200);

            log.debug("更新笔记排行榜: noteId={}, score={}, like={}, collect={}", 
                    noteId, stats.hotScore, stats.likeCount, stats.collectCount);

        } catch (Exception e) {
            log.error("更新笔记排行榜失败: noteId={}", noteId, e);
        }
    }

    /**
     * 更新书评排行榜到 Redis
     */
    private void updateReviewRanking(String reviewId, String statsJson) {
        try {
            ReviewStats stats = JSON.parseObject(statsJson, ReviewStats.class);

            // 更新实时热门书评排行榜
            cacheService.zAdd(KafkaConfig.Keys.REVIEW_REALTIME_HOT_RANKING, reviewId, stats.hotScore);
            
            // 更新书评点赞排行榜
            cacheService.zAdd(KafkaConfig.Keys.REVIEW_LIKE_RANKING, reviewId, stats.likeCount);
            
            // 更新书评收藏排行榜
            cacheService.zAdd(KafkaConfig.Keys.REVIEW_COLLECT_RANKING, reviewId, stats.collectCount);

            // 只保留 Top 500，设置2小时过期
            trimAndExpireRanking(KafkaConfig.Keys.REVIEW_REALTIME_HOT_RANKING, 500, 7200);
            trimAndExpireRanking(KafkaConfig.Keys.REVIEW_LIKE_RANKING, 500, 7200);
            trimAndExpireRanking(KafkaConfig.Keys.REVIEW_COLLECT_RANKING, 500, 7200);

            log.debug("更新书评排行榜: reviewId={}, score={}, like={}, collect={}, helpful={}", 
                    reviewId, stats.hotScore, stats.likeCount, stats.collectCount, stats.helpfulCount);

        } catch (Exception e) {
            log.error("更新书评排行榜失败: reviewId={}", reviewId, e);
        }
    }

    /**
     * 图书统计数据内部类
     */
    private static class BookStats {
        public int viewCount = 0;           // 浏览次数
        public int readingCount = 0;        // 阅读人数
        public int likeCount = 0;           // 点赞数
        public int collectCount = 0;        // 收藏数
        public int noteCount = 0;           // 笔记数
        public int reviewCount = 0;         // 书评数
        public int totalReadingTime = 0;    // 总阅读时长（秒）
        public double popularityScore = 0;  // 热度分数
        public long lastUpdateTime = System.currentTimeMillis();
        
        // 使用 Set 存储阅读用户ID（去重）
        public java.util.Set<Integer> readingUserIds = new java.util.HashSet<>();
    }

    /**
     * 用户统计数据内部类
     */
    private static class UserStats {
        public int behaviorCount = 0;       // 行为次数
        public int readingTime = 0;         // 阅读时长（分钟）
        public long lastUpdateTime = System.currentTimeMillis();
    }

    /**
     * 笔记统计数据内部类
     */
    private static class NoteStats {
        public int viewCount = 0;           // 浏览次数
        public int likeCount = 0;           // 点赞数
        public int collectCount = 0;        // 收藏数
        public int commentCount = 0;        // 评论数
        public double hotScore = 0;         // 热度分数
        public long lastUpdateTime = System.currentTimeMillis();
    }

    /**
     * 书评统计数据内部类
     */
    private static class ReviewStats {
        public int viewCount = 0;           // 浏览次数
        public int likeCount = 0;           // 点赞数
        public int collectCount = 0;        // 收藏数
        public int commentCount = 0;        // 评论数
        public int helpfulCount = 0;        // 有用标记数
        public double hotScore = 0;         // 热度分数
        public long lastUpdateTime = System.currentTimeMillis();
    }
}

